package 拓扑排序;

import java.util.*;

/**
 * @author: AirMan
 * @date: 2025/6/8 13:22
 * @description:
 */
public class Main {
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        int v = sc.nextInt();
        int e = sc.nextInt();

        boolean[][] edge = new boolean[v][v];

        for (int i = 0; i < e; i++) {
            int v1 = sc.nextInt();
            int v2 = sc.nextInt();
            edge[v1][v2] = true;
        }
        // 统计节点的入度
        int[] indegree = new int[v];
        for (int i = 0; i < v; i++) {
            for (int j = 0; j < v; j++) {
                if (edge[i][j]) {
                    indegree[j]++;
                }
            }
        }

        // 将入度为0的节点收集到队列中
        Deque<Integer> queue = new LinkedList<>();
        for (int i = 0; i < v; i++) {
            if (indegree[i] == 0) {
                queue.add(i);
            }
        }
        int count = 0; // 统计处理的节点数
        List<Integer> list = new ArrayList();
        // 遍历其他节点，移除当前入度为0的节点，删除该节点的边，并将边所指的其他节点的度数更新
        while (!queue.isEmpty()) {
            Integer nowNode = queue.poll();
            list.add(nowNode);
            count++;
            // 删除该节点所关联的边（也就是更新另一个端点的入度）
            for (int i = 0; i < v; i++) {
                // 更新过程中，如果入度为0则入栈
                if (edge[nowNode][i] && (--indegree[i] == 0)) {
                    queue.add(i);
                }
            }
        }
        if (count < v){
            System.out.print("-1");
        }else{
            for(int i = 0; i < list.size() - 1; i++){
                System.out.print(list.get(i) + " ");
            }
            System.out.print(list.get(list.size() - 1));
        }
    }
}
